package org.dandsoft.blackbox.snn;

import org.dandsoft.blackbox.ObjectId;
import org.dandsoft.blackbox.Value;
import org.dandsoft.blackbox.util.list.Entry;
import org.dandsoft.blackbox.util.list.EntryList;

import java.util.Iterator;

/**
 * User: dvilyuzhanin
 * Date: 19.01.2009 18:18:50
 */
public class Neuron {

    private ObjectId id;
    private Enviroment enviroment;
    private final Entry<Neuron> usedEntry = new Entry<Neuron>(this);
    private EntryList<Synapse> activeSynapsys = new EntryList<Synapse>();
    private Value value;

    public synchronized void addActiveSynapseEntry(Entry<Synapse> synapseEntry) throws SnnException {
        Synapse synapse = synapseEntry.getObject();
        if (!synapse.getDestination().equals(id)) {
            throw new WrongDestinationNeuronException(id, synapse.getId(), synapse.getDestination());
        } else {
            activeSynapsys.add(synapseEntry);
        }
    }

    public synchronized void activate() throws SnnException {
        Synapse synapse;
        Value value = Value.NULL;
        while ((synapse = activeSynapsys.nextObject()) != null) {
            Value synapseValue = synapse.getValue();
            if (synapseValue.isActive()) {
                value = value.add(synapse.getWeight());
            }
        }

        this.value = value;

        Iterator<Synapse> iterator = enviroment.getSynapsesBySource(id);
        while (iterator.hasNext()) {
            Synapse outputSynapse = iterator.next();
            outputSynapse.prepare(this.value);
        }
    }

    public synchronized void used() throws SnnException {
        enviroment.addToUsedNeuronsList(usedEntry);
    }

    public synchronized Enviroment getEnviroment() {
        return enviroment;
    }

    public synchronized void setEnviroment(Enviroment enviroment) {
        this.enviroment = enviroment;
    }

    public synchronized Value getValue() {
        return value;
    }

    public synchronized void setValue(Value value) {
        this.value = value;
    }

    public synchronized ObjectId getId() {
        return id;
    }

    public synchronized void setId(ObjectId id) {
        this.id = id;
    }
}
